﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.UI;
using AVISOutBound.SSOServer.Orders;
using AVISOutBound.SSOServer.Orders.AbgOrderPayLogs;
using AVISOutBound.SSOServer.Orders.AbgRefundOrders;
using AVISOutBound.SSOServer.Payment.Dto;
using System.Linq.Dynamic.Core;
using Abp.AutoMapper;
using AVISOutBound.SSOServer.Payment.Wechat;

namespace AVISOutBound.SSOServer.Payment
{
    /// <summary>
    /// 退款单服务
    /// </summary>
    public class RefundOrderAppService: ApplicationService,IRefundOrderAppService
    {
        private IRepository<AbgOrderPayLog, long> _payOrderRepository;
        private IRepository<AbgRefundOrder, long> _refundOrdeRepository;
        private IOrderRepository _orderRepository;

        private IOrderManager _orderManager;
        private IAlipayManager _alipayManager;
        private IWechatManager _wechatManager;

        public RefundOrderAppService(
            IRepository<AbgOrderPayLog, long> payOrderRepository
            , IRepository<AbgRefundOrder, long> refundOrdeRepository
            , IOrderRepository orderRepository
            , IOrderManager orderManager
            , IAlipayManager alipayManager
            , IWechatManager wechatManager)
        {
            _payOrderRepository = payOrderRepository;
            _refundOrdeRepository = refundOrdeRepository;
            _orderRepository = orderRepository;

            _orderManager = orderManager;
            _alipayManager = alipayManager;
            _wechatManager = wechatManager;
        }

        /// <summary>
        /// 申请退款
        /// </summary>
        /// <param name="input">输入参数</param>
        /// <returns></returns>
        public async Task Apply(CreateRefundOrderInput input)
        {
            var order = this._orderManager.GetDBOrder(input.OrderNo);

            if (order == null)
            {
                throw new UserFriendlyException("订单不存在");
            }

            if (order.OrderStatus == (int) OrderStatus.Cancel || order.IsCancel)
            {
                throw new UserFriendlyException("订单已取消");
            }

            if (order.OrderStatus == (int)OrderStatus.Finish)
            {
                throw new UserFriendlyException("订单已完成");
            }

            if (order.OrderStatus.HasValue && order.OrderStatus == (int)OrderStatus.Normal)
            {
                throw new UserFriendlyException("订单尚未支付");
            }

            //var amount = Convert.ToDecimal(order.Amount);
            // TODO:由于测试原因，默认退款金额0.01元
            var amount = Convert.ToDecimal(0.01);

            var payInfo = this._payOrderRepository.FirstOrDefault(x =>
                x.OrderNo == order.OrderNo && x.Status == (int)PayStatus.Success);
            if (payInfo == null)
            {
                throw new UserFriendlyException("不存在订单支付信息");
            }

            if (amount > Convert.ToDecimal(payInfo.Amount))
            {
                throw new UserFriendlyException("超出可退款金额");
            }

            await CreateRefundOrder(input, $"RO{DateTime.Now:yyyyMMddHHmmss}", Convert.ToSingle(payInfo.Amount),
                (PayType) payInfo.PayType);
        }

        /// <summary>
        /// 创建退款单
        /// </summary>
        /// <param name="input">输入参数</param>
        /// <param name="orderNo">订单号</param>
        /// <param name="amount">退款金额</param>
        /// <param name="payType">支付方式</param>
        /// <returns></returns>
        private async Task CreateRefundOrder(CreateRefundOrderInput input,string orderNo, float? amount,PayType payType)
        {
            var exists = this._refundOrdeRepository.LongCount(x =>
                x.OrderNo == input.OrderNo && (x.RefundStatus == 1 || x.RefundStatus == 2));
            if (exists > 0)
            {
                throw new UserFriendlyException("已存在退款申请");
            }

            AbgRefundOrder entity = new AbgRefundOrder()
            {
                Amount = amount,
                Cause = input.Cause,
                Reason = input.Reason,
                OrderNo = input.OrderNo,
                RefundOrderNo = orderNo,
                RefundWay = (int) payType,
                RefundType = 1,
                UserId = AbpSession.UserId ?? 0,
                RefundStatus = (int)RefundStatus.Normal
            };

            await this._refundOrdeRepository.InsertAsync(entity);
        }

        /// <summary>
        /// 同意退款
        /// </summary>
        /// <param name="refundOrderNo">退款单号</param>
        /// <returns></returns>
        public async Task Agree(string refundOrderNo)
        {
            var entity = await this._refundOrdeRepository.FirstOrDefaultAsync(x => x.RefundOrderNo == refundOrderNo);
            if (entity == null)
            {
                throw new UserFriendlyException("退款申请不存在");
            }

            if (entity.RefundStatus != (int)RefundStatus.Normal)
            {
                throw new UserFriendlyException("退款申请已审核");
            }

            await Refund(entity);
        }

        /// <summary>
        /// 退款
        /// </summary>
        /// <param name="refundOrder">退款单</param>
        /// <returns></returns>
        private async Task Refund(AbgRefundOrder refundOrder)
        {
            var order = this._orderManager.GetDBOrder(refundOrder.OrderNo);
            if (order == null)
            {
                throw new UserFriendlyException("订单不存在");
            }

            var payInfo = this._payOrderRepository.FirstOrDefault(x =>
                x.OrderNo == order.OrderNo && x.Status == (int) PayStatus.Success);
            if (payInfo == null)
            {
                throw new UserFriendlyException("支付单不存在");
            }

            if (payInfo.PayType == (int)PayType.Alipay)
            {
                var refundResult = this._alipayManager.Refund(payInfo.PayOrderNo, payInfo.OutOrderNo,
                    Convert.ToDecimal(payInfo.Amount).ToString("F"), "正常退款", refundOrder.RefundOrderNo);
                if (!refundResult.IsSuccess)
                {
                    throw new UserFriendlyException("退款失败" + refundResult.ErrorMessage);
                }

                refundOrder.OutRefundOrderNo = refundResult.TradeNo;
                refundOrder.RefundStatus = (int)RefundStatus.Success;

                await this._refundOrdeRepository.UpdateAsync(refundOrder);

                order.OrderStatus = (int) OrderStatus.Cancel;
                order.IsCancel = true;
                await this._orderRepository.UpdateOrderStatus(order);
                // TODO:调用取消订单接口
            }
            else if (payInfo.PayType == (int) PayType.Wechat)
            {
                var refundResult = this._wechatManager.Refund(new WechatRefundParam()
                {
                    OutTradeNo = payInfo.PayOrderNo,
                    TotalFee = Convert.ToDecimal(payInfo.Amount),
                    RefundFee = Convert.ToDecimal(payInfo.Amount),
                    OutRefundNo = refundOrder.RefundOrderNo,
                    DeviceInfo = "WAP",
                });

                if (!refundResult.IsSuccess)
                {
                    throw new UserFriendlyException("退款失败" + refundResult.ErrorMessage);
                }
                refundOrder.OutRefundOrderNo = refundResult.WechatOrderNo;
                refundOrder.RefundStatus = (int)RefundStatus.Success;

                await this._refundOrdeRepository.UpdateAsync(refundOrder);
                order.OrderStatus = (int)OrderStatus.Cancel;
                order.IsCancel = true;
                await this._orderRepository.UpdateOrderStatus(order);
                // TODO:调用取消订单接口
            }
            else
            {
                throw new UserFriendlyException("不支持的退款方式");
            }            
        }

        /// <summary>
        /// 拒绝退款
        /// </summary>
        /// <param name="input">输入参数</param>
        /// <returns></returns>
        public async Task Reject(RejectRefundInput input)
        {
            var entity = await this._refundOrdeRepository.FirstOrDefaultAsync(x => x.RefundOrderNo == input.RefundOrderNo);
            if (entity == null)
            {
                throw new UserFriendlyException("退款申请不存在");
            }

            if (entity.RefundStatus != (int)RefundStatus.Normal)
            {
                throw new UserFriendlyException("退款申请已审核");
            }

            entity.RefundStatus = (int) RefundStatus.Fail;
            entity.SellMemo = input.SellMemo;

            await this._refundOrdeRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 获取退款单分页列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public PagedResultDto<RefundOrderOutput> GetPaged(GetRefundOrderInput input)
        {
            // 初步过滤
            var query = this._refundOrdeRepository.GetAll()
                .WhereIf(!string.IsNullOrWhiteSpace(input.OrderNo), x => x.OrderNo == input.OrderNo);
            // 排序
            query = !string.IsNullOrWhiteSpace(input.Sorting)
                ? query.OrderBy(input.Sorting)
                : query.OrderByDescending(x => x.CreationTime);

            // 获取总数
            var count = query.Count();
            var list = query.PageBy(input).ToList();
            return new PagedResultDto<RefundOrderOutput>(count, list.MapTo<List<RefundOrderOutput>>());
        }
    }
}
